<?php
 
/**
 * DataStore package.
 *
 * @package DataStore
 * @author matthijs
 * @author arjan.top
 * @author Chris Corbyn
 */
  
require_once dirname(__FILE__) . '/StorageModel.php';

/**
 * Class DataStore
 *
 * @package DataStore
 */ 
class DataStore {
 
  /**
   * The storage model
   * @access private
   * @var object
   */
  private $_storageModel;
 
  /**
   * The private store of data
   * @access private
   * @var array
   */
  private $_store = array();
 
  /**
   * Constructor takes a {@link StorageModel} for reading and writing.
   * @param StorageModel $storageModel
   */
  public function __construct(StorageModel $storageModel) {
    $this->_storageModel = $storageModel;
    $this->_store = (array) $this->_storageModel->load();
  }
 
  /**
   * Sets a value based on input $key and $value
   * @param string $key
   * @param string $value
   */
  public function set($key, $value) {
    $container =& $this->_getContainer($key, true);
    $container[$this->_getEndKey($key)] = $value;
  }
 
  /**
   * Gets a value based on input $key
   * @param string $key
   * @return mixed
   */
  public function get($key) {
    if ($this->has($key)) {
      $container =& $this->_getContainer($key);
      return $container[$this->_getEndKey($key)];
    }
  }
 
  /**
   * Returns true or false if input $key exists
   * @param string $key
   * @return boolean
   */
  public function has($key) {
    $container =& $this->_getContainer($key);
    return (is_array($container)
      && array_key_exists($this->_getEndKey($key), $container));
  }
 
  /**
   * Removes a $value from the store based on input $key
   * @param string $key
   */
  public function remove($key) {
    if ($this->has($key)) {
      $container =& $this->_getContainer($key);
      unset($container[$this->_getEndKey($key)]);
    }
  }
 
  /**
   * Save the current state of the store
   * @param StorageModel $storageModel  
   * @return boolean
   */
  public function save(StorageModel $storageModel = null) {
    if (!isset($storageModel)) {
      $storageModel = $this->_storageModel;
    }
    return $storageModel->save($this->_store);
  }
 
  // -- Private methods
 
  /**
   * @access private
   * @param string $key
   * @return string
   */
  private function _getEndKey($key) {
    $keys = explode('/', $key);
    return array_pop($keys);
  }
 
  /**
   * @access private
   * @param $key
   * @param $creatIfNotFound
   * @return array
   */
  private function &_getContainer($key, $createIfNotFound = false) {
    $container =& $this->_store;
    foreach (array_slice(explode('/', $key), 0, -1) as $nextKey) {
      if (!array_key_exists($nextKey, $container)) {
        if (!$createIfNotFound) {
          return false;
        }
        $container[$nextKey] = array();
      }
      $container =& $container[$nextKey];
    }
    return $container;
  }
 
}
